package com.xt.base.dao.hibernate.code;

import java.lang.reflect.Method;
import java.util.Set;

import org.aopalliance.aop.Advice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.support.DynamicMethodMatcherPointcut;

public class CodePointcutAdvisor extends DynamicMethodMatcherPointcut implements PointcutAdvisor{
	
	private static final ThreadLocal<Set<IAutoCreateCode>> targets = new ThreadLocal<Set<IAutoCreateCode>>();
	
	public Pointcut getPointcut() {
		return this;
	}

	public Advice getAdvice() {
		return new MethodBeforeAdvice(){
			public void before(Method method, Object[] args, Object target) throws Throwable {
				try{
					for(IAutoCreateCode iac: 
						getTarget())CodeGenerator.setCode(iac,null);
				}finally{
					targets.set(null);
				}
			}
		};
	}

	public boolean isPerInstance() {
		return false;
	}

	@SuppressWarnings("unchecked")
	public boolean matches(Method method,Class clazz){
		String name = method.getName();
		return "save".equals(name)||"saveObject".equals(name);
	}

	@SuppressWarnings("unchecked")
	public boolean matches(Method method, Class clazz, Object[] args){
		boolean res = false;
		if(args==null||args.length==0) return res;
		if(args[0] instanceof IAutoCreateCode){
			Set<IAutoCreateCode> t = getTarget((IAutoCreateCode)args[0]);
			res = !t.isEmpty();
		}
		return 	res;
	}
	
	public ClassFilter getClassFilter(){
		return new ClassFilter(){
			@SuppressWarnings("unchecked")
			public boolean matches(Class clazz){
				return clazz.getPackage()!=null &&	clazz.getPackage().getName().indexOf("com.xt")==0;
			}
		};
	}
	
	private Set<IAutoCreateCode> getTarget(IAutoCreateCode arg){
		Set<IAutoCreateCode> res = targets.get();
		if(res == null){
			res = arg.getTargets();
			targets.set(res.isEmpty()?null:res);
		}
		return res;
	}
	private Set<IAutoCreateCode> getTarget(){
		return targets.get();
	}

}
